﻿using FirstFloor.ModernUI.Presentation;
using SelElectCalcModernUI.Model;
using SelElectCalcModernUI.Service;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace SelElectCalcModernUI.ViewModel.Settings
{
    /// <summary>
    /// A simple view model for configuring theme, font and accent colors.
    /// </summary>
    public class AppearanceViewModel
        : NotifyPropertyChanged, IDisposable
    {
        private const string FontSmall = "small";
        private const string FontLarge = "large";
        private AppearanceDataModel appearanceData;

        // 9 accent colors from metro design principles
        /*private Color[] accentColors = new Color[]{
            Color.FromRgb(0x33, 0x99, 0xff),   // blue
            Color.FromRgb(0x00, 0xab, 0xa9),   // teal
            Color.FromRgb(0x33, 0x99, 0x33),   // green
            Color.FromRgb(0x8c, 0xbf, 0x26),   // lime
            Color.FromRgb(0xf0, 0x96, 0x09),   // orange
            Color.FromRgb(0xff, 0x45, 0x00),   // orange red
            Color.FromRgb(0xe5, 0x14, 0x00),   // red
            Color.FromRgb(0xff, 0x00, 0x97),   // magenta
            Color.FromRgb(0xa2, 0x00, 0xff),   // purple            
        };*/

        // 20 accent colors from Windows Phone 8
        private Color[] accentColors = new Color[]{
            Color.FromRgb(0xa4, 0xc4, 0x00),   // lime
            Color.FromRgb(0x60, 0xa9, 0x17),   // green
            Color.FromRgb(0x00, 0x8a, 0x00),   // emerald
            Color.FromRgb(0x00, 0xab, 0xa9),   // teal
            Color.FromRgb(0x1b, 0xa1, 0xe2),   // cyan
            Color.FromRgb(0x00, 0x50, 0xef),   // cobalt
            Color.FromRgb(0x6a, 0x00, 0xff),   // indigo
            Color.FromRgb(0xaa, 0x00, 0xff),   // violet
            Color.FromRgb(0xf4, 0x72, 0xd0),   // pink
            Color.FromRgb(0xd8, 0x00, 0x73),   // magenta
            Color.FromRgb(0xa2, 0x00, 0x25),   // crimson
            Color.FromRgb(0xe5, 0x14, 0x00),   // red
            Color.FromRgb(0xfa, 0x68, 0x00),   // orange
            Color.FromRgb(0xf0, 0xa3, 0x0a),   // amber
            Color.FromRgb(0xe3, 0xc8, 0x00),   // yellow
            Color.FromRgb(0x82, 0x5a, 0x2c),   // brown
            Color.FromRgb(0x6d, 0x87, 0x64),   // olive
            Color.FromRgb(0x64, 0x76, 0x87),   // steel
            Color.FromRgb(0x76, 0x60, 0x8a),   // mauve
            Color.FromRgb(0x87, 0x79, 0x4e),   // taupe
        };
        
        private LinkCollection themes = new LinkCollection();

        public AppearanceViewModel()
        {
            // add the default themes
            this.themes.Add(new Link { DisplayName = "dark", Source = AppearanceManager.DarkThemeSource });
            this.themes.Add(new Link { DisplayName = "light", Source = AppearanceManager.LightThemeSource });

            appearanceData = SaveLoadData.LoadSkinData<AppearanceDataModel>();

            if (AppearanceData.SelectedAccentColor != null && 
                AppearanceData.SelectedAccentColor.A!=0 && 
                AppearanceData.SelectedAccentColor.B != 0 && 
                AppearanceData.SelectedAccentColor.G != 0 )
                AppearanceManager.Current.AccentColor = AppearanceData.SelectedAccentColor;
            else
                AppearanceData.SelectedAccentColor = AppearanceManager.Current.AccentColor;
            if (AppearanceData.SelectedFontSize != null)
                AppearanceManager.Current.FontSize = AppearanceData.SelectedFontSize == FontLarge ? FontSize.Large : FontSize.Small;
            else
                AppearanceData.SelectedFontSize = FontSmall;
            if (!String.IsNullOrEmpty(AppearanceData.SelectedThemeName))
                AppearanceManager.Current.ThemeSource = this.themes.FirstOrDefault(l => l.DisplayName.Equals(AppearanceData.SelectedThemeName)).Source;
            else
                AppearanceData.SelectedThemeName = "light";

            AppearanceManager.Current.PropertyChanged += OnAppearanceManagerPropertyChanged;
            AppearanceData.PropertyChanged += (sender, e) =>
            {
                switch (e.PropertyName)
                {
                    case "SelectedAccentColor":
                        AppearanceManager.Current.AccentColor = AppearanceData.SelectedAccentColor;
                        break;
                    case "SelectedFontSize":
                        AppearanceManager.Current.FontSize = AppearanceData.SelectedFontSize == FontLarge ? FontSize.Large : FontSize.Small;
                        break;
                    case "SelectedThemeName":
                        AppearanceManager.Current.ThemeSource = this.themes.FirstOrDefault(l => l.DisplayName.Equals(AppearanceData.SelectedThemeName)).Source;
                        break;
                    default:
                        break;
                }
            };
        }

        private void SyncThemeAndColor()
        {
            // synchronizes the selected viewmodel theme with the actual theme used by the appearance manager.
            this.AppearanceData.SelectedThemeName = this.themes.FirstOrDefault(l => l.Source.Equals(AppearanceManager.Current.ThemeSource)).DisplayName;

            // and make sure accent color is up-to-date
            this.AppearanceData.SelectedAccentColor = AppearanceManager.Current.AccentColor;
        }

        private void OnAppearanceManagerPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ThemeSource" || e.PropertyName == "AccentColor")
            {
                SyncThemeAndColor();
            }
        }
        
        public LinkCollection Themes
        {
            get { return this.themes; }
        }
        
        public string[] FontSizes
        {
            get { return new string[] { FontSmall, FontLarge }; }
        }
        
        public Color[] AccentColors
        {
            get { return this.accentColors; }
        }
        
        public AppearanceDataModel AppearanceData
        {
            get
            {
                if (appearanceData == null)
                    appearanceData = new AppearanceDataModel();
                return appearanceData;
            }
        }
        
        public Link SelectedTheme
        {
            get { return this.themes.FirstOrDefault(l => l.DisplayName.Equals(AppearanceData.SelectedThemeName)); }
            set
            {
                if (AppearanceData.SelectedThemeName != value.DisplayName)
                {
                    AppearanceData.SelectedThemeName = value.DisplayName;
                    OnPropertyChanged("SelectedTheme");

                    // and update the actual theme
                    AppearanceManager.Current.ThemeSource = value.Source;
                }
            }
        }
        public void Dispose()
        {
            SaveLoadData.SaveSkinData(this.AppearanceData);
        }
    }
}
